package com.gui.juc.container;

import com.gui.utils.Sleeper;

import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ConcurrentHashMapDemo1 {

    static ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>(512);

    public static void main(String[] args) {

        ThreadPoolExecutor threadPool =
                new ThreadPoolExecutor(10, 10, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(1000));
        for (int i = 0; i < 200; i++) {
            threadPool.submit(new PutValueToMapSafeTask(map));
        }
        Sleeper.sleep(TimeUnit.SECONDS, 10);
        threadPool.shutdown();
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + "-->" + entry.getValue());
        }

    }

    static class PutValueToMapTask implements Runnable{

        private ConcurrentHashMap<String, Integer> map;

        public PutValueToMapTask(ConcurrentHashMap<String, Integer> map) {
            this.map = map;
        }

        @Override
        public void run() {
            /**
             * 这里涉及两个方法 一个 get 一个 put
             * 两个方法单独来看是线程安全的，但是合在一起就不能保证原子性了
             */
            for (int i = 0; i < 20; i++) {
                Integer value = map.get("" + i);
                if (value == null) {
                    map.put("" + i, 1);
                }else {
                    map.put("" + i, value + 1);
                }
            }
        }
    }


    static class PutValueToMapSafeTask implements Runnable{

        private ConcurrentHashMap<String, Integer> map;

        public PutValueToMapSafeTask(ConcurrentHashMap<String, Integer> map) {
            this.map = map;
        }

        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                map.merge("" + i, 1, Integer::sum);
            }
        }
    }
}
